#!/usr/bin/env python3
# encoding: utf-8

"""
@version: 1.0
@author: 周永波
@file: filters.py
@time: 2020/8/10 15:43
"""
# 统一返回值处理 开始 --------------------------------
import json
import uuid

import requests
from flask import Response, request, redirect, make_response
from traitlets import Bool

from demoApp.setting.cache import CacheUtils
from demoApp.util import appUtils


class retHandler:

    @staticmethod
    def ret_before():
        # print("req")
        pass

    @staticmethod
    def ret_after(res: Response):
        return res

    @staticmethod
    def ret_exception(e):
        pass


# 统一返回值处理 结束 --------------------------------

# 第三方登录
whiteList = set(['/client/login'])
suffixMatch = set(['.js', '.html', '.jpg', '.png'])


def session_set(user_info):
    sessionKey = str(uuid.uuid1())
    CacheUtils.set_val(sessionKey, user_info)
    rule = request.url_rule
    if rule is None:
        rule = ''
    resp = make_response(redirect(rule))
    resp.set_cookie('FLASK_TOKEN', sessionKey)
    return resp


class OauthServer:

    def __init__(self, config={}) -> None:
        self.oauth_server = appUtils.dict_get(config, ['oauth', 'server'])
        self.client_id = appUtils.dict_get(config, ['oauth', 'client_id'])
        self.client_secret = appUtils.dict_get(config, ['oauth', 'client_secret'])

        self.authorize = '/oauth/authorize'
        self.oauth_token = '/oauth/token'
        self.me = '/me'
        self.response_type = 'code'
        self.state = 'oauth'

    def redirect_login(self):
        redirect_url = request.base_url
        redict = self.oauth_server + self.authorize + '?client_id=' + self.client_id + '&redirect_uri=' + redirect_url + '&response_type=' \
                 + self.response_type + '&state=' + self.state
        return redirect(redict)

    def check_oauth(self):
        args = request.args
        code = args.get('code')
        if code is None:
            return
        state = args.get('state')
        if state is None or state != self.state:
            return
        # 进行access_token 的 获取
        return self.access_token(code)

    def access_token(self, code: str):
        redirect_url = request.base_url
        code_url = self.oauth_server + self.oauth_token + '?client_id=' + self.client_id + '&redirect_uri=' + redirect_url + '&client_secret=' \
                + self.client_secret + '&grant_type=authorization_code&code=' + code
        rest = requests.post(code_url)
        if rest.status_code == 200:
            data = json.loads(rest.content)
            access_token = data['access_token']
            refresh_token = data['refresh_token']
            return self.login_user_info(access_token)
        else:
            return make_response('授权失败:access_token')

    def login_user_info(self, access_token: str):
        access_token_url = self.oauth_server + self.me + '?access_token=' + access_token
        rest = requests.get(access_token_url)
        if rest.status_code == 200:
            data = json.loads(rest.content)
            # 进行cookie的设置
            return session_set(data)
        else:
            return make_response('获取用户信息失败')


# 授权操作对象
oauth_server: OauthServer

class OauthLogin:

    def __init__(self, config={}) -> None:
        global oauth_server
        oauth_server = OauthServer(config)
        # oauth_server = appUtils.dict_get(config,('oauth','server'))

    @staticmethod
    def is_not_login() -> bool:
        requestPath = str(request.url_rule)
        if requestPath is None:
            requestPath = ''
        for suffix in suffixMatch:
            if requestPath.endswith(suffix):
                return True
        for white in whiteList:
            if requestPath.endswith(white):
                return True
        return False

    @staticmethod
    def is_login():
        flask_token = request.cookies.get('FLASK_TOKEN')
        if flask_token is None:
            return oauth_server.redirect_login()
        val = CacheUtils.get_val(flask_token)
        if val is None:
            return oauth_server.redirect_login()

    @staticmethod
    def ret_before():
        res_oauth = oauth_server.check_oauth()
        if res_oauth is not None:
            return res_oauth

        if OauthLogin.is_not_login():
            return

        is_login = OauthLogin.is_login()
        if is_login is not None:
            return is_login

    @staticmethod
    def ret_after(res: Response):
        return res

    @staticmethod
    def ret_exception(e):
        pass
